<?php
/*
available types : int, string
current page : start at index => 1 ! (not 0)
types of listing : 'table' or 'list'
filter values examples : if type == string : 'po' or 'ip' or 'ods' for 'ipods' / if type == int : '|20' or 14|16 or 10| for 15 //TODO : type date
*/

/*
$testContentData = array(
	'settings' => array(
		'column_with_id' => 'id',
		'editable' => true,
		'removable' => true,
		'viewable' => true,
		'columns' => array(
			'id' => array(
				'title' => 'ID',
				'displayed' => true,
				'filterable' => true,
				'sortable' => true,
				'editable' => false
			),
			'name' => array(
				'title' => 'The Name',
				'displayed' => true,
				'filterable' => true,
				'sortable' => true,
				'editable' => true
			),
			'price' => array(
				'title' => 'The Price',
				'displayed' => true,
				'filterable' => true,
				'sortable' => true,
				'editable' => true
			),
			'comm' => array(
				'title' => 'The Commentaries',
				'displayed' => true,
				'filterable' => false,
				'sortable' => false,
				'editable' => true
			),
			'date_add' => array(
				'title' => 'Added the :',
				'displayed' => true,
				'filterable' => true,
				'sortable' => true,
				'editable' => false
			),
			'hour' => array(
				'title' => 'The hour was :',
				'displayed' => true,
				'filterable' => true,
				'sortable' => true,
				'editable' => false
			),
			'datetime_add' => array(
				'title' => 'Exactly added :',
				'displayed' => true,
				'filterable' => true,
				'sortable' => true,
				'editable' => false
			)
		)
	)
);

$testContentData['content'] = array (
  0 => 
  array (
	 'id' => 1,
	 'name' => 'hot dog',
	 'price' => '25',
	 'comm' => 'Lorem Ipsum',
	 'date_add' => '2008-11-27',
	 'hour' => '2008-11-27 17:08:17',
	 'datetime_add' => '2008-11-27 17:08:17'
  ),
  1 => 
  array (
	 'id' => 2,
	 'name' => 'chips',
	 'price' => '35',
	 'comm' => 'A B C',
	 'date_add' => '2008-11-27',
	 'hour' => '2008-11-27 17:08:17',
	 'datetime_add' => '2008-11-27 17:08:17'
  ),
  2 => 
  array (
	 'id' => 3,
	 'name' => 'ketchup',
	 'price' => '25.5',
	 'comm' => 'Ici un test',
	 'date_add' => '2008-11-27',
	 'hour' => '2008-11-27 17:08:17',
	 'datetime_add' => '2008-11-27 17:08:17'
  ),
  3 => 
  array (
	 'id' => 4,
	 'name' => 'ketchup',
	 'price' => '17.50',
	 'comm' => 'Ici un test',
	 'date_add' => '2008-11-27',
	 'hour' => '2008-11-27 17:08:17',
	 'datetime_add' => '2008-11-27 17:08:17'
  ),
  4 => 
  array (
	 'id' => 5,
	 'name' => 'ketchup',
	 'price' => '25.5',
	 'comm' => 'Ici un test',
	 'date_add' => '2008-11-27',
	 'hour' => '2008-11-27 17:08:17',
	 'datetime_add' => '2008-11-27 17:08:17'
  ),
  5 => 
  array (
	 'id' => 6,
	 'name' => 'ketchup',
	 'price' => '25.5',
	 'comm' => 'Ici un test',
	 'date_add' => '2008-11-27',
	 'hour' => '2008-11-27 17:08:17',
	 'datetime_add' => '2008-11-27 17:08:17'
  ),
  6 => 
  array (
	 'id' => 7,
	 'name' => 'ketchup',
	 'price' => '25.5',
	 'comm' => 'Ici un test',
	 'date_add' => '2008-11-27',
	 'hour' => '2008-11-27 17:08:17',
	 'datetime_add' => '2008-11-27 17:08:17'
  ),
  7 => 
  array (
	 'id' => 8,
	 'name' => 'ketchup',
	 'price' => '25.5',
	 'comm' => 'Ici un test',
	 'date_add' => '2008-11-27',
	 'hour' => '2008-11-27 17:08:17',
	 'datetime_add' => '2008-11-27 17:08:17'
  ),
  8 => 
  array (
	 'id' => 9,
	 'name' => 'ketchup',
	 'price' => '25.5',
	 'comm' => 'Ici un test',
	 'date_add' => '2008-11-27',
	 'hour' => '2008-11-27 17:08:17',
	 'datetime_add' => '2008-11-27 17:08:17'
  ),
  9 => 
  array (
	 'id' => 10,
	 'name' => 'ketchup',
	 'price' => '25.5',
	 'comm' => 'Ici un test',
	 'date_add' => '2008-11-27',
	 'hour' => '2008-11-27 17:08:17',
	 'datetime_add' => '2008-11-27 17:08:17'
  ),
  10 => 
  array (
	 'id' => 11,
	 'name' => 'ketchup',
	 'price' => '25.5',
	 'comm' => 'Ici un test',
	 'date_add' => '2008-11-27',
	 'hour' => '2008-11-27 17:08:17',
	 'datetime_add' => '2008-11-27 17:08:17'
  ),
  11 => 
  array (
	 'id' => 12,
	 'name' => 'ketchup',
	 'price' => '25.5',
	 'comm' => 'Ici un test',
	 'date_add' => '2008-11-27',
	 'hour' => '2008-11-27 17:08:17',
	 'datetime_add' => '2008-11-27 17:08:17'
  ),
  12 => 
  array (
	 'id' => 13,
	 'name' => 'ketchup',
	 'price' => '25.5',
	 'comm' => 'Ici un test',
	 'date_add' => '2008-11-27',
	 'hour' => '2008-11-27 17:08:17',
	 'datetime_add' => '2008-11-27 17:08:17'
  ),
  13 => 
  array (
	 'id' => 14,
	 'name' => 'ketchup',
	 'price' => '25.5',
	 'comm' => 'Ici un test',
	 'date_add' => '2008-11-27',
	 'hour' => '2008-11-27 17:08:17',
	 'datetime_add' => '2008-11-27 17:08:17'
  ),
  14 => 
  array (
	 'id' => 15,
	 'name' => 'ketchup',
	 'price' => '25.5',
	 'comm' => 'Ici un test',
	 'date_add' => '2008-11-27',
	 'hour' => '2008-11-27 17:08:17',
	 'datetime_add' => '2008-11-27 17:08:17'
  ),
  15 => 
  array (
	 'id' => 16,
	 'name' => 'ketchup',
	 'price' => '25.5',
	 'comm' => 'Ici un test',
	 'date_add' => '2008-11-27',
	 'hour' => '2008-11-27 17:08:17',
	 'datetime_add' => '2008-11-27 17:08:17'
  ),
  16 => 
  array (
	 'id' => 17,
	 'name' => 'ketchup',
	 'price' => '25.5',
	 'comm' => 'Ici un test',
	 'date_add' => '2008-11-27',
	 'hour' => '2008-11-27 17:08:17',
	 'datetime_add' => '2008-11-27 17:08:17'
  ),
  17 => 
  array (
	 'id' => 18,
	 'name' => 'ketchup',
	 'price' => '25.5',
	 'comm' => 'Ici un test',
	 'date_add' => '2008-11-27',
	 'hour' => '2008-11-27 17:08:17',
	 'datetime_add' => '2008-11-27 17:08:17'
  ),
  18 => 
  array (
	 'id' => 19,
	 'name' => 'ketchup',
	 'price' => '25.5',
	 'comm' => 'Ici un test',
	 'date_add' => '2008-11-27',
	 'hour' => '2008-11-27 17:08:17',
	 'datetime_add' => '2008-11-27 17:08:17'
  ),
  19 => 
  array (
	 'id' => 20,
	 'name' => 'ketchup',
	 'price' => '25.5',
	 'comm' => 'Ici un test',
	 'date_add' => '2008-11-27',
	 'hour' => '2008-11-27 17:08:17',
	 'datetime_add' => '2008-11-27 17:08:17'
  ),
  20 => 
  array (
	 'id' => 21,
	 'name' => 'ketchup',
	 'price' => '25.5',
	 'comm' => 'Ici un test',
	 'date_add' => '2008-11-27',
	 'hour' => '2008-11-27 17:08:17',
	 'datetime_add' => '2008-11-27 17:08:17'
  ),
  21 => 
  array (
	 'id' => 22,
	 'name' => 'ketchup',
	 'price' => '25.5',
	 'comm' => 'Ici un test',
	 'date_add' => '2008-11-27',
	 'hour' => '2008-11-27 17:08:17',
	 'datetime_add' => '2008-11-27 17:08:17'
  ),
  22 => 
  array (
	 'id' => 23,
	 'name' => 'ketchup',
	 'price' => '25.5',
	 'comm' => 'Ici un test',
	 'date_add' => '2008-11-27',
	 'hour' => '2008-11-27 17:08:17',
	 'datetime_add' => '2008-11-27 17:08:17'
  ),
  23 => 
  array (
	 'id' => 24,
	 'name' => 'ketchup',
	 'price' => '25.5',
	 'comm' => 'Ici un test',
	 'date_add' => '2008-11-27',
	 'hour' => '2008-11-27 17:08:17',
	 'datetime_add' => '2008-11-27 17:08:17'
  ),
);
*/

class Listing {
	public $listing_name;
	
	/* display settings */
	public $currentPage;
	public $itemsPerPage;
	public $type;
	public $sortByColumn;
	public $sortByDirection;
	public $filterColumn;
	public $filterValue;
	public $numberOfPagesNumbersToShow;
	
	/*content data */
	public $data;
	public $editable;
	public $removable;
	public $viewable;
	public $column_with_id;
	public $multiple_action;
	public $columnsSettings;
	
	/* calculated values */
	public $nbPages;
	public $nbItems;
	
	public function __construct($listing_name, $contentData, $alreadyFiltered = false, $currentPage = 1, $itemsPerPage = 50, $typeOfListing = 'table', $sortByColumn = null, $sortByDirection = 'ASC', $filterColumn = null, $filterValue = null, $numberOfPagesNumbersToShow = 3) {
		
		$this->numberOfPagesNumbersToShow = $numberOfPagesNumbersToShow;
		
		$this->listing_name = $listing_name;
		
		//set each columns settings
		$this->columnsSettings = $contentData['settings']['columns'];
		
		//set multiple action
		$this->multiple_action = $contentData['settings']['multiple_action'];
		
		$this->column_with_id = $contentData['settings']['column_with_id'];
		
		//autodetect column types
		foreach ($this->columnsSettings as $keyColumnSettings => &$columnSettings)
		{
			$type = '';
			if (!empty($contentData['content']))
			{
				foreach ($contentData['content'] as $line)
				{
					if (($type != 'numeric' && $type != 'string') && strtotime($line[$keyColumnSettings]) !== false && strtotime($line[$keyColumnSettings]) != time())
						$type = 'date';
					elseif ($type != 'string' && is_numeric($line[$keyColumnSettings]) !== false)
						$type = 'numeric';
					else
						$type = 'string';
				}
				$columnSettings['type'] = $type;
			}
		}
		
		//filter results
		$this->filterColumn = $filterColumn;
		$this->filterValue = $filterValue;
		
		if (!$alreadyFiltered && $this->filterColumn && $this->columnsSettings[$this->filterColumn]['filterable'] && $this->filterValue && $this->filterValue != '')
		{
			$type = $this->columnsSettings[$this->filterColumn]['type'];
				foreach ($contentData['content'] as $key => $content_line)
				{
					$columnValue = $content_line[$this->filterColumn];
					if ($type == 'numeric')
					{
						$valuesRange = explode('|' , $this->filterValue);
						if(count($valuesRange) > 1)
						{
							$minValue = floatval($valuesRange[0]);
							$maxValue = floatval($valuesRange[1]);
							if ($valuesRange[0] > $columnValue || ($valuesRange[1] > 0 && $columnValue > $valuesRange[1]))
								unset($contentData['content'][$key]);
						}
						else
						{
							if ($columnValue != $this->filterValue)
								unset($contentData['content'][$key]);
						}
					}
					elseif ($type == 'string')
					{
						if (strrpos(strtolower(_escape_accents($columnValue)), strtolower(_escape_accents($this->filterValue))) === false)
							unset($contentData['content'][$key]);
					}
					
					
				}
		}
		//sort the results
		$this->sortByDirection = $sortByDirection;
		if($sortByColumn == null)
		{
			$columnsName = $this->getColumnsNames();
			$columnsName = array_keys($columnsName);
			$this->sortByColumn = $columnsName[0];
		}
		else
		{
			$this->sortByColumn = $sortByColumn;
		}
		if (!$alreadyFiltered && !empty($contentData['content']))
		{
			$sortingArray = array();
			foreach ($contentData['content'] as $key => $content_line)
					$sortingArray[$key] = $content_line[$this->sortByColumn];
			array_multisort($sortingArray, $sortByDirection == 'DESC' ? SORT_DESC : SORT_ASC, $contentData['content']);
		}
		
		//reduce the results for the specified page and limit the number of items to display per page
		$this->itemsPerPage = $itemsPerPage;
		_p($contentData);
		$this->nbPages = max(ceil(count($contentData['content']) / $this->itemsPerPage),1);
		$this->currentPage = $currentPage <= $this->nbPages ? $currentPage : 1;
		
		$this->data = ($alreadyFiltered OR !is_array($contentData['content'])) ? $contentData['content'] : array_slice($contentData['content'], ($this->currentPage-1) * $this->itemsPerPage, $this->itemsPerPage);
		
		//autoadd minimum and maximum values to the numeric columns
		foreach ($this->columnsSettings as $keyColumnSettings => &$columnSettings)
		{
			if ($columnSettings['type'] == 'numeric')
			{
				$columnSettings['minimum'] = $this->getLowestNumeric($keyColumnSettings);
				$columnSettings['maximum'] = $this->getHighestNumeric($keyColumnSettings);
				$columnSettings['float_precision'] = $this->getFloatPrecision($keyColumnSettings);
			}
		}
		
		//set the type of listing
		$this->type = $typeOfListing;
		
		$this->nbItems = count($contentData['content']);
		
		$this->editable = $contentData['settings']['editable'];
		$this->removable = $contentData['settings']['removable'];
		$this->viewable = $contentData['settings']['viewable'];
		
		
		/* check data validity */
		//TODO
	}
	
	public function fetch(){
		global $smarty;
		$smarty->assign('listing', $this);
		return $smarty->fetch('listing.tpl');
	}
	
	public function fetchAjax(){
		global $smarty;
		$smarty->assign('listing', $this);
		return $smarty->fetch('ajax_listing.tpl');
	}
	
	private function getHighestNumeric($columnsName) {
		$ret = array();
		$highest = reset($this->data);
		$highest = floatval($highest[$columnsName]);
		foreach ($this->data as $key => $value)
			if(floatval($value[$columnsName]) > $highest)
				$highest = floatval($value[$columnsName]);
		return $highest;
	}
	
	private function getLowestNumeric($columnsName) {
		$ret = array();
		$lowest = reset($this->data);
		$lowest = floatval($lowest[$columnsName]);
		
		foreach ($this->data as $key => $value)
			if(floatval($value[$columnsName]) < $lowest)
				$lowest = floatval($value[$columnsName]);
		return $lowest;
	}
	
	private function getFloatPrecision($columnsName) {
		
		$ret = array();
		$highest = reset($this->data);
		$value = floatval($highest[$columnsName]);
		$highest = ($pointPosition = strpos($value, '.')) ? (strlen($value) - $pointPosition - 1) : 0;
		foreach ($this->data as $key => $value)
		{
			$aValue = floatval($value[$columnsName]);
			$tmp = ($pointPosition = strpos($aValue, '.')) ? (strlen($aValue) - $pointPosition - 1) : 0;
			if($tmp > $highest)
				$highest = $tmp;
		}
		return $highest;
	}
	
	public function getColumnsNames() {
		$ret = array();
		foreach ($this->columnsSettings as $key => $value)
			if (isset($value['title']))
				$ret[$key] = $value['title'];
		return $ret;
	}
}
